package gogen

import (
	_ "embed"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/zeromicro/go-zero/tools/goctl/api/spec"
	"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)

//go:embed router.tpl
var routerTemplate string

var Router = "router"

func genRouter(dir string, rootPkg string, api *spec.ApiSpec) error {
	var (
		// admin:NewAdmin
		logics = make(map[string]string)
		// service: [admin, user]
		handlers = make(map[string]string)
	)

	var moduls []string
	for s, apiSpec := range api.Srvs {
		logicFlags := make([]string, len(apiSpec.Service.Logics))
		for k, v := range apiSpec.Service.Logics {
			t := strings.TrimSpace(v)
			flag := fmt.Sprintf("%sLogic", strings.ToLower(t[:1])+t[1:])
			logics[flag] = fmt.Sprintf("New%s", t)
			logicFlags[k] = flag
		}

		handlers[s] = strings.Join(logicFlags, ",")
		if apiSpec.Module == "" {

			continue
		}

		moduls = append(moduls, apiSpec.Module)
	}

	newHandles, handlerList := genRouterNewHandles(handlers)

	filename := filepath.Join(dir, fmt.Sprintf("%s/%s/%s.go", handlerDir, api.Module, Router))

	os.Remove(filename)

	return genFile(fileGenConfig{
		dir:             dir,
		subdir:          fmt.Sprintf("%s/%s", handlerDir, api.Module),
		filename:        "router.go",
		templateName:    "routerTemplate",
		templateFile:    "router.tpl",
		builtinTemplate: routerTemplate,
		data: map[string]string{
			"pkgName":     api.Module,
			"imports":     genRouterImports(rootPkg, api.Module, moduls),
			"newLogics":   genRouterNewLogics(logics),
			"newHandles":  newHandles,
			"handlerList": handlerList,
		},
	})
}
func genRouterNewLogics(logics map[string]string) string {
	var res strings.Builder
	res.Write([]byte("var (\n"))
	for flag, newLogic := range logics {
		res.Write([]byte(fmt.Sprintf("\t\t%s = %s.%s(svc)\n", flag, Logic, newLogic)))
	}
	res.Write([]byte("\t)"))
	return res.String()
}

func genRouterNewHandles(handlers map[string]string) (newHandlers string, handlerList string) {
	var (
		news  strings.Builder
		flags strings.Builder
	)

	news.Write([]byte("var (\n"))
	for s, logics := range handlers {

		if strs := strings.Split(s, "/"); len(strs) > 1 {
			flag := strings.ToLower(strs[1][:1]) + strs[1][1:] + strings.ToUpper(strs[0][:1])+strs[0][1:]
			flags.Write([]byte(fmt.Sprintf("%s,\n", flag)))
			news.Write([]byte(fmt.Sprintf("\t\t%s = %s.New%s(svc", flag, strs[0], strings.ToUpper(strs[1][:1])+strs[1][1:])))
		} else {
			flag := strings.ToLower(s[:1]) + s[1:]
			flags.Write([]byte(fmt.Sprintf("%s,\n", flag)))
			news.Write([]byte(fmt.Sprintf("\t\t%s = New%s(svc", flag, strings.ToUpper(s[:1])+s[1:])))
		}

		if len(logics) > 0 {
			news.Write([]byte(fmt.Sprintf(", %s", logics)))
		}
		news.Write([]byte(")\n"))
	}
	news.Write([]byte("\t)"))

	return news.String(), flags.String()
}

func genRouterImports(parentPkg string, apiModule string, modules []string) string {
	var imports []string
	//imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, configDir)))
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, logicDir)))
	imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, contextDir)))

	for _, v := range modules {
		imports = append(imports, fmt.Sprintf("\"%s\"", pathx.JoinPackages(parentPkg, handlerDir+"/"+apiModule+"/"+v)))
	}

	return strings.Join(imports, "\n\t")
}
